<?php
/**
 * Object representing a user
 *
 * @package Concerto
 * @subpackage Models
 * @author Jason Raede <jason@torchdm.com>
 */
namespace application\models;
use application\utilities\Utility;
use application\system\Permalink;

class User extends ContentBase {
	
	/**
	 * Array of fields according to the form they appear on
	 *
	 * @var array
	 */
	protected $forms = array();
	
	/**
	 * Initialize the object with its database data if $id is provided, and
	 * load the fields according to the user form settings
	 *
	 * @param int $id
	 */
	public function __construct($id = null) {
		global $concerto;
		if($id) {
			$row = DB()->getRow("SELECT * FROM `cn_users` WHERE `user_id`='$id'");
			foreach($row as $column=>$value) {
				$this->$column = $value;
			}
			
			$this->data['content_type'] = $contentType;
		}
		
		$fields =  DB()->getResults("SELECT * FROM `cn_content_fields` WHERE `cf_content_type`='0'");
		
		
		foreach($fields as $field) {
			$this->fields[$field->cf_display_name] = $field;
			$this->forms['edit_profile'][$field->cf_display_name] = $field;
			if($field->cf_show_signup) $this->forms['signup'][$field->cf_display_name] = $field;
			if($field->cf_column == 'user_email') {
				$this->forms['forgot_password'][$field->cf_display_name] = $field;
				$this->forms['login'][$field->cf_display_name] = $field;
			}
			if($field->cf_column == 'user_password') {
				$this->forms['login'][$field->cf_display_name] = $field;
			}
			
			$column = ($field->cf_order_column) ? $field->cf_order_column : 1;
			if($field->cf_column != 'user_id')
				$this->fieldColumns[$column][] = $field;
			
			// Parse data to split it into 
			$this->fromDB($field);
		}
		
	}
	
	/**
	 * Checks if the user is a global admin
	 * 
	 * @return bool
	 */
	public function isAdmin() {
		return ($this->dbFields['user_level'] >= 2) ? TRUE : FALSE;
	}
	
	/**
	 * Returns the display name of the user according to the user configuration settings
	 *
	 * @return string
	 */
	public function displayName() {
		// Get the settings from user config
		$identification = getOption('user_identification');
		switch($identification) {
			case 'email':
				$return = $this->dbFields['user_email'];
				break;
			case 'username':
			default:
				if($username = $this->dbFields['user_username']) 
					$return = $username;
				else
					$return = $this->dbFields['user_email'];
				break;
			case 'custom':
				$custom = getOption('user_identification_custom');
				foreach($this->fields as $display=>$field) {
					$custom = str_replace('{'.$display.'}', $this->dbFields[$field->cf_column], $custom);
				}
				$return = $custom;
				break;
			
		}
			
		
		return Modulator()->runFilter('user_display_name', $return, $this->dbFields);
	}
	
	/**
	 * Regenerates the user's password and send them an e-mail
	 *
	 * @param int $id The user's id
	 */
	public static function resetPassword($id) {
		$password = Utility::strRand(8);
		DB()->update('cn_users', 'user_id', $id, array('user_password'=>md5($password)));
		
		$email = DB()->getVar("SELECT `user_email` FROM `cn_users` WHERE `user_id`='$id'");
		// Send a message with his password
		$mail = mail($email, 'Reset Password', 'As requested, your password has been reset '.CN_SITE_NAME.'. You can login by going to '.CN_URL.'login/. Your new temporary password is '.$password.'; you can change it when you log in.', 'From: '.CN_SITE_NAME.' Admin  <no-reply@tavorinteractive.com>');
	}
	
	/**
	 * Update or insert the database row and perform all actions associated with adding a new user
	 *
	 * @param array $fields Fields to add. Leave null for all fields
	 */
	public function save($fields = null) {
		$this->getFormData();
		$this->toDB($fields);
		$return = array();
		if(!count($this->messages['error'])) {
			if($id = $this->data['user_id']) { // Update
				DB()->update('cn_users', 'user_id', $id, $this->dbFields['cn_users']);
				
				if(count($this->dbFields['auxData'])) {
					foreach($this->fields as $field) {
						$class = 'application\\datatypes\\' . $field->cf_data_type;
						$class::save($this->dbFields['auxData'], $id, 0);
					}
				}
				$this->messages['success'][] = 'Profile updated successfully.';
			}
			else { // Add
				// Make sure there's not already a user with that email or username
				$email = strtolower($this->dbFields['cn_users']['user_email']);
				$username = strtolower($this->dbFields['cn_users']['user_username']);
				$emailCount = DB()->getCount("SELECT `user_id` FROM `cn_users` WHERE `user_email`='$email'");
				$usernameCount = DB()->getCount("SELECT `user_id` FROM `cn_users` WHERE `user_username`='$username'");
				if($emailCount) {
					$this->messages['error'][] = 'There is already a user with this email address.';
				}
				else if($usernameCount && $username) {
					$this->messages['error'][] = 'There is already a user with this username.';
				}
				else {
					unset($this->dbFields['cn_users']['user_id']);
					// Generate a password
					$password = Utility::strRand(8);
					$this->dbFields['cn_users']['user_password'] = md5($password);
					
					// Level is -1 if they need approval
					if(getOption('user_admin_approval') && getQueryVar('form') == 'signup') {
						$this->dbFields['cn_users']['user_level'] = '-1';
					}
					DB()->insert('cn_users', $this->dbFields['cn_users']);
					
					$last = DB()->lastInsert();
					if(count($this->dbFields['auxData'])) {
						foreach($this->fields as $field) {
							$class = 'application\\datatypes\\' . $field->cf_data_type;
							$class::save($this->dbFields['auxData'], $last);
						}
					}
					
					
					
					// Send a message with his password
					
					$id = $last;
					
					if(getOption('user_admin_approval')) {
						
						if(getQueryVar('form') == 'signup') {
						
							$this->messages['success'][] = 'Congratulations! You have successfully created your account. You will receive a notification when the administrators approve your account.';
							$mail = mail($email, 'New Account at ' . CN_SITE_NAME, 'We have received your registration request at '.CN_SITE_NAME.'. You will receive a notification when the administrators approve your account. If you did not create an account, please ignore this e-mail.', 'From: '.CN_SITE_NAME.' Admin  <no-reply@torchdm.com>');
						}
						else {
							$this->messages['success'][] = 'User added successfully.';
							$mail = mail($email, 'New Account at ' . CN_SITE_NAME, 'You have been successfully registered at '.CN_SITE_NAME.'. You can login by going to '.CN_URL.'login/. Your temporary password is '.$password.'. You can change it when you log in. If you did not create an account, please ignore this e-mail.', 'From: '.CN_SITE_NAME.' Admin  <no-reply@torchdm.com>');
						}
					}
					else {
						$mail = mail($email, 'New Account at ' . CN_SITE_NAME, 'You have been successfully registered at '.CN_SITE_NAME.'. You can login by going to '.CN_URL.'login/. Your temporary password is '.$password.'; you can change it when you log in. If you did not create an account, please ignore this e-mail.', 'From: '.CN_SITE_NAME.' Admin  <no-reply@torchdm.com>');
						if(getQueryVar('form') == 'signup') 
						
							$this->messages['success'][] = 'Congratulations! You have successfully created your account. You will receive your temporary password shortly at the e-mail address you provided.';
						else 
							$this->messages['success'][] = 'User added successfully.';
					}
				}
			}
			
			return array('status'=>'success', 'id'=>$id);
		}
		else {
			return array('status'=>'error', 'errors'=>$this->messages['error']);
		}
		
	}
	
	
	/**
	 * Validates all data on this object with their respective DataType classes
	 * 
	 * @see \application\datatypes\DataType::validate()
	 * @param array $fields Fields to validate
	 */
	protected function toDB($fields = null) {
		$results = array();
		// Use datatype-defined methods of validation
		if(!$fields) $fields = $this->fields;
		foreach($fields as $field) {
			$class = '\\application\\datatypes\\'.$field->cf_data_type;
			$results = $class::validate($field, $this->data, $results);
			
		}
		if(is_array($results['errors'])) {
			$this->messages['error'] = $results['errors'];
		}
		else {
			
			$cn_users = array();
			$auxData = array();
			foreach($results['db_fields'] as $field=>$value) {
				if(substr($field, 0, 4) == 'user') {
					$cn_users[$field] = $value;
				}
				else {
					$auxData[$field] = $value;
				}
			}
			// Set the content type
			$cn_users['user_id'] = $this->data['user_id'];
			
			$this->dbFields['cn_users'] = $cn_users;
			$this->dbFields['auxData'] = $auxData;
			
		}
	}
	
	/**
	 * Handles validation of special forms that require password checking, etc
	 *
	 * @return bool If the form query variable matched a valid special form
	 */
	public function validateSpecificForm() {
		$validated = FALSE;
		switch(getQueryVar('form')) {
			case 'edit_profile':
				$validated = TRUE;
				$password = $_REQUEST['user_password_current'];
				if(md5($password) != DB()->getVar("SELECT `user_password` FROM `cn_users` WHERE `user_id`='".$this->data['user_id']."'")) {
					$results['errors'][] = 'Your current password is incorrect.';
				}
				foreach($this->fields as $field) {
					$class = '\\application\\datatypes\\'.$field->cf_data_type;
					$results = $class::validate($field, $this->data, $results);
					
				}
				if(count($results['errors'])) {
					if(is_array($results['errors'])) {
						$this->messages['error'] = $results['errors'];
					}
				}
				else {
					$this->save();
				}
				break;
			case 'login':
				$validated = TRUE;
				$email = $_REQUEST['user_email'];
				$password = md5($_REQUEST['user_password_password1']);
				$emailCheck = DB()->getCount("SELECT `user_id` FROM `cn_users` WHERE `user_email`='$email'");
				if(!$emailCheck) {
					$results['errors'][] = 'There is no user registered with that e-mail address.';
				}
				
				// Check for pending
				elseif(DB()->getVar("SELECT `user_level` FROM `cn_users` WHERE `user_email`='$email'") < 0) {
					$results['errors'][] = 'Your account is still pending approval from the administrators. You will receive an e-mail notification when your account has been approved.';

				}
				else {
					$userId = DB()->getVar("SELECT `user_id` FROM `cn_users` WHERE `user_email`='$email' AND `user_password`='$password'");
					if(!$userId) $results['errors'][] = 'Password is incorrect.';
				}
				
				
				if(count($results['errors'])) {
					if(is_array($results['errors'])) {
						$this->messages['error'] = $results['errors'];
					}
				}
				else {
					/** Everything checks out, so set the session user ID and redirect them to the page designated on the admin panel */
					$_SESSION['cn_user_id'] = $userId;
					$this->messages['success'][] = 'Logged in successfully.';
					if($redirect = getQueryVar('redirect')) header('location:http://'.$redirect);
					
					else {
						// Get redirect rules from user configuration
						$redirect = getOption('user_post_login_redirect');
						switch($redirect) {
							case 'dashboard':
								$location = Permalink::systemPermalink('dashboard');
								break;
							case 'home':
								$location = CN_URL;
								break;
							case 'custom':
								$location = getOption('user_post_login_custom');
								break;
						}
						header('location:'.$location);
					}
					
				}
				break;
			case 'forgot_password':
				$validated = TRUE;
				$email = $_REQUEST['user_email'];
				if($id = DB()->getVar("SELECT `user_id` FROM `cn_users` WHERE `user_email`='$email'")) {
					// Generate a new password
					self::resetPassword($id);
					$this->messages['success'][] = "Password reset. You will receive your new temporary password via e-mail.";
				}
				else {
					$this->messages['error'][]= "Sorry, there is no user registered with that e-mail address.";
				}
				break;
		}
		
		return $validated;
	}
	
	/**
	 * @deprecated
	 */
	public function displaySpecificForm($form) {
		// Display one of the user forms
		

	}
	
	/**
	 * Delete the user and all related data from the database
	 */
	public function delete() {
		DB()->query("DELETE FROM `cn_users` WHERE user_id`='".$this->data['user_id']."'");
		DB()->query("DELETE FROM `cn_user_user_relations` WHERE `uur_user1`='".$this->data['user_id']."' OR `uur_user2`='".$this->data['user_id']."'");
		DB()->query("DELETE FROM `cn_feedback` WHERE `feedback_user`='".$this->data['user_id']."'");
		DB()->query("DELETE FROM `cn_user_content_relations` WHERE `ucr_user`='".$this->data['user_id']."'");
		
		return array('status'=>'success');
	}	

	
	
	
}

?>